﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using QuailDb;

namespace QuailDashboard.View.Web
{
	/// <summary>
	/// NOTE: If you change the interface name "IQuailDataService" here, you must also update the reference to "IQuailDataService" in Web.config.
	/// </summary>
	[ServiceContract]
	public interface IQuailDataService
	{
		/// <summary>
		/// Gets the current remote control status
		/// </summary>
		/// <returns>a list of remote control status</returns>
		[OperationContract]
		List<RemoteControlStatus> GetCurrentRemoteControlStatus();

		/// <summary>
		/// Gets a list of test run tasks for a given testrunid and parentid
		/// </summary>
		/// <param name="testrunid">the test run id</param>
		/// <param name="parenttestruntaskid">the parent id</param>
		/// <returns>the list of tasks</returns>
		[OperationContract]
		List<TestRunTask> GetTestRunTask(int testrunid, long parenttestruntaskid);

		/// <summary>
		/// Gets all the attributes for a test run task
		/// </summary>
		/// <param name="testruntaskid">The TestRunTaskID</param>
		/// <returns></returns>
		[OperationContract]
		List<TestRunTaskAttribute> GetTestRunTaskAttribute(long testruntaskid);

		/// <summary>
		/// Gets All the log entries for a test run task
		/// </summary>
		/// <param name="testruntaskid">The TestRunTaskID</param>
		/// <returns></returns>
		[OperationContract]
		List<TestRunTaskLogEntry> GetTestRunTaskLogEntry(long testruntaskid);

		
		/// <summary>
		/// Gets a test run task for a given TestRunTaskId.
		/// </summary>
		/// <param name="testRunTaskId">Int TestRunTaskId</param>
		/// <returns>The TestRunTask</returns>
		[OperationContract]
		TestRunTask GetTestRunTaskById(long testRunTaskId);


		/// <summary>
		/// Gets all the Log Entries for a given testrunid
		/// </summary>
		/// <param name="testrunid"></param>
		/// <returns></returns>
		[OperationContract]
		List<TestRunTaskLogEntry> GetAllTestRunTaskLogEntry(int testrunid);

		/// <summary>
		/// Gets a list of remote control hosts
		/// </summary>
		/// <returns></returns>
		[OperationContract]
		List<RemoteControlHostList> GetRemoteControlHostList();

		/// <summary>
		/// Gets the specified remote control host
		/// </summary>
		/// <param name="hostname">The host name</param>
		/// <returns></returns>
		[OperationContract]
		RemoteControlHostList GetRemoteControlHost(string hostname);

		/// <summary>
		/// Adds a remote control host to the system (obsolete: use ConfigureRemoteControlWithMaxUsage instead)
		/// </summary>
		/// <param name="hostname">The host name</param>
		/// <param name="port">The port</param>
		/// <param name="notes">Optional notes for the host</param>
		[Obsolete]
		[OperationContract]
		void AddRemoteControl(string hostname, int port, string notes);

		/// <summary>
		/// Enables or disables a remote control host (obsolete: use ConfigureRemoteControlWithMaxUsage instead)
		/// </summary>
		/// <param name="hostname">The hostname</param>
		/// <param name="enable"></param>
		/// <returns></returns>
		[Obsolete]
		[OperationContract]
		bool EnableRemoteControl(string hostname, bool enable);

		/// <summary>
		/// Configures a new or existing remote control host  (obsolete: use ConfigureRemoteControlWithMaxUsage instead)
		/// </summary>
		/// <param name="hostname">The hostname</param>
		/// <param name="port">The port</param>
		/// <param name="enable">A flag to enable or disable the host</param>
		/// <returns>True if the configuration was made.</returns>
		[Obsolete]
		[OperationContract]
		bool ConfigureRemoteControl(string hostname, int port, bool enable);

		/// <summary>
		/// Configures a new or existing remote control host.
		/// </summary>
		/// <param name="hostname">The hostname</param>
		/// <param name="port">The port</param>
		/// <param name="enable">A flag to enable or disable the host</param>
		/// <param name="maxUsageCount">The maximum number of simultaneous requests the host can handle.  NULL or zero = Unbounded</param>
		/// <returns>True if the configuration was made.</returns>
		[OperationContract]
		bool ConfigureRemoteControlWithMaxUsage(string hostname, int port, bool enable, int maxUsageCount);

		/// <summary>
		/// Sets the capabilities for a given remote control host
		/// </summary>
		/// <param name="hostname">The hostname</param>
		/// <param name="capabilities">List of capabilities</param>
		/// <returns>True if the set was successful, falst otherwise</returns>
		[OperationContract]
		bool SetRemoteControlCapabilities(string hostname, List<string> capabilities);

		/// <summary>
		/// Gets a list of existing remote control capabilities
		/// </summary>
		/// <returns>The list of capabilities</returns>
		[OperationContract]
		List<RemoteControlCapability> GetAllRemoteControlCapabilities();

		/// <summary>
		/// Gets a list of remote control capabilities for a host
		/// </summary>
		/// <returns>The list of capabilities</returns>
		[OperationContract]
		List<RemoteControlCapability> GetRemoteControlCapabilities(string hostname);

		/// <summary>
		/// Adds a list of remote control capabilities to the system
		/// </summary>
		/// <param name="capabilities">The list of new (or existings) capabilities</param>
		[OperationContract]
		void AddRemoteControlCapabilities(List<RemoteControlCapability> capabilities);

		/// <summary>
		/// Gets a binary file by name
		/// </summary>
		/// <param name="filename">The filename</param>
		/// <returns>The Blob for the file</returns>
		[Obsolete]
		[OperationContract]
		Blob GetBinaryFile(string filename);

		/// <summary>
		/// Gets a dictionary mapping each recently used data group to a list of num test / num thread pairs that it's been run with
		/// </summary>
		/// <returns>the dictionary</returns>
		[OperationContract]
		Dictionary<string, List<Tuple<int?, int?>>> GetTestsAndThreadsByGroup();

		/// <summary>
		/// Gets a list of recently used numbers of tests and threads in load tests
		/// </summary>
		/// <returns>A list of tuples, each representing a number of tests and a number of threads</returns>
		[OperationContract]
		List<Tuple<int?, int?>> GetTestsAndThreads();

		/// <summary>
		/// Gets a list of recently used test environments
		/// </summary>
		/// <returns>A list of environments</returns>
		[OperationContract]
		List<TestEnvironment> GetEnvironments();

		/// <summary>
		/// Gets a list of all test environments
		/// </summary>
		/// <returns>A list of environments</returns>
		[OperationContract]
		List<TestEnvironment> GetAllEnvironments();

		/// <summary>
		/// Gets a TestEnvironment object by environment name
		/// </summary>
		/// <param name="name">The environment name</param>
		/// <returns>A TestEnvironment object or null</returns>
		[OperationContract]
		TestEnvironment GetEnvironment(string name);


		[OperationContract]
		List<TestMonitor> GetTestMonitors(int environmentId, int monitorTypeId, int taskStatusId, string message, int maxResults);


		[OperationContract]
		List<TestMonitorType> GetTestMonitorTypes();


		/// <summary>
		/// Gets a list of all test library runs for an environment/test library id (optional)
		/// </summary>
		/// <returns>A list of TestLibrary objects</returns>
		[OperationContract]
		List<ViewTestLibraryRun> GetTestLibraryRuns(int? testLibraryId, int testEnvironmentId, DateTime? minDateTime, DateTime? maxDateTime);

		/// <summary>
		/// Gets the most recent test library run
		/// </summary>
		/// <returns>A TestLibraryRun object, or null</returns>
		[OperationContract]
		ViewTestLibraryRun GetMostRecentTestLibraryRun(int testLibraryId, int testEnvironmentId);

		/// <summary>
		/// Gets the test library run by testLibraryRunId
		/// </summary>
		/// <returns>A TestLibraryRun object, or null</returns>
		[OperationContract]
		ViewTestLibraryRun GetTestLibraryRun(int testLibraryRunId);

		/// <summary>
		/// Gets the test runs by testLibraryRunId
		/// </summary>
		/// <returns>A list of ViewTestRun objects</returns>
		[OperationContract]
		List<ViewTestRun> GetTestRunsForTestLibraryRun(int testLibraryRunId);

		/// <summary>
		/// Gets a list of test names by testLibraryId
		/// </summary>
		/// <returns>A list of test names</returns>
		[OperationContract]
		List<TestClassName> GetTestNamesForTestLibrary(int testLibraryId);


		/// <summary>
		/// Gets a list of all test libraries
		/// </summary>
		/// <returns>A list of TestLibrary objects</returns>
		[OperationContract]
		List<TestLibrary> GetLibraries();

		/// <summary>
		/// Gets a list of all test class names
		/// </summary>
		/// <returns>A list of ViewTestClassName</returns>
		[OperationContract]
		List<ViewTestClassName> GetTestClassNames();

		/// <summary>
		/// Gets a list of Task Statuses
		/// </summary>
		/// <returns>A list of TaskStatus</returns>
		[OperationContract]
		List<TaskStatus> GetTaskStatuses();

		/// <summary>
		/// Gets the run status for a given environment and test classname
		/// </summary>
		/// <param name="testenvironmentid">the environment</param>
		/// <param name="testclassname">the test class name</param>
		/// <returns>A list of GetRunStatusResults</returns>
		[OperationContract]
		List<GetRunStatusResult> GetRunStatus(int testenvironmentid, string testclassname);

		[OperationContract]
		List<GetRunStatusResult> GetRunStatusForDate(int testenvironmentid, DateTime dt);

		[OperationContract]
		List<GetRunStatusResult> GetRunStatusForForTestAndDate(int testenvironmentid, string testclassname, DateTime? dt);

		[OperationContract]
		List<GetRunStatusResult> GetRunStatusForTestsAndDate(int testenvironmentid, string[] testclassname, DateTime? dt);

		[OperationContract]
		List<SearchTestRunTaskResult> SearchForTestRunTask(int testrunid, long? testruntaskid, bool ascending, string searchtext, string tasktatusidlist);

		[OperationContract]
		ViewTestRun GetTestRun(int testrunid);

		[OperationContract]
		TestNote AddTestNote(int testid, string userid, string note);

		[OperationContract]
		void ActivateTestNote(int testnoteid, bool activate);

		[OperationContract]
		List<TestNote> GetTestNotes(int testid, bool activeonly);

		[OperationContract]
		TestNote GetTestNote(int testnoteid);

		[OperationContract]
		TestNote UpdateTestNote(TestNote notedata);

		[OperationContract]
		string GetCurrentUser();

		[OperationContract]
		bool SetTestOwner(int testenvironmentid, int testid, string newowner, bool force, out string owner);

		[OperationContract]
		bool ClearTestOwner(int testenvironmentid, int testid, string oldowner, bool force, out string owner);

		[OperationContract]
		TestRunTask GetTestRunTaskData(long testruntaskid);

		[OperationContract]
		void UpdateTestEnvironment(int testenvironmentid, string name, string description);

		[OperationContract]
		int AddTestEnvironment(string name, string description);

		[OperationContract]
		List<GetEnvironmentSettingResult> GetEnvironmentSettings(int testenvironmentid);

		[OperationContract]
		GetEnvironmentSettingResult GetEnvironmentSettingValue(int testenvironmentid, string settingname);

		[OperationContract]
		void SetEnvironmentSettingValue(int testenvironmentid, string settingname, string settingvalue);

		[OperationContract]
		void DeleteEnvironmentSetting(int testenvironmentid, string settingname);

		/// <summary>
		/// Gets the next available remote control host from the Quail pool
		/// </summary>
		/// <param name="testname">the name of the test</param>
		/// <param name="capabilities">list of needed capabilities</param>
		/// <returns>The new host or NULL if no host is available</returns>
		[OperationContract]
		GetNextRemoteControlHostResult GetNextRemoteControlHost(string testname, string[] capabilities);

		/// <summary>
		/// Releases a remote control host so it can be used for another test.  Use the hostkey returned from GetNextRemoteControlHost
		/// </summary>
		/// <param name="hostkey">The hostkey returned from GetNextRemoteControlHost</param>
		[OperationContract]
		void ReleaseRemoteControlHost(int hostkey);

		/// <summary>
		/// Returns a list of load testing groups
		/// </summary>
		/// <returns>List of load test groups</returns>
		[OperationContract]
		List<string> GetLoadTestGroups();

		/// <summary>
		/// Returns a list of load testing data
		/// </summary>
		/// <param name="dataGroup">Specify a specific data group (optional)</param>
		/// <returns>List of LoadTestData objects</returns>
		[OperationContract]
		List<LoadTestData> GetLoadTestData(string dataGroup);

		/// <summary>
		/// Starts load test run
		/// </summary>
		/// <param name="testRunId">The TestRunId for the load test</param>
		/// <param name="testEnvironmentId">The TestEnvironmentId for the load test (optional if testRunId is provided)</param>
		/// <param name="numTests">the number of individual tests run</param>
		/// <param name="numThreads">the number of threads used</param>
		/// <returns>The LoadTestId - use in FinishLoadTest</returns>
		[OperationContract]
		int CreateLoadTest(int? testRunId, int? testEnvironmentId, int? numTests, int?numThreads);

		/// <summary>
		/// Adds a test run to the database
		/// </summary>
		/// <param name="loadTestId">The load test id returned from CreateLoadTest()</param>
		/// <param name="loadTestDataId">The load test data Id from LoadTestData</param>
		/// <param name="msToFirstByte">The ms to first byte</param>
		/// <param name="msToLastByte">The ms to last byte</param>
		/// <param name="size">The total size of the content</param>
		/// <param name="statusCode">The status code</param>
		/// <param name="startDate">The time the individual test started</param>
		[OperationContract]
		void AddLoadTestUrlRun(int loadTestId,
							   int loadTestDataId,
							   int[] msToFirstByte,
							   int[] msToLastByte,
							   int[] size,
							   int[] statusCode,
							   DateTime?[] startDate);

		/// <summary>
		/// Completes a load test
		/// </summary>
		/// <param name="loadTestId">The load test id returned from CreateLoadTest()</param>
		[OperationContract]
		void FinishLoadTest(int loadTestId);

		/// <summary>
		/// Gets a load test run detail for a given datagroup, url and testEnvironmentId
		/// </summary>
		/// <param name="dataGroup">The data group</param>
		/// <param name="url">The url</param>
		/// <param name="testEnvironmentId">The test environment id</param>
		/// <param name="startDate">The start date range</param>
		/// <param name="endDate">The end date range</param>
		/// <param name="numTests">Only get runs with this number of tests, if non-zero</param>
		/// <param name="numThreads">Only get runs with this number of threads, if non-zero</param>
		/// <returns>A list of LoadTestRunData objects</returns>
		[OperationContract]
		List<LoadTestRunData> GetLoadTestRuns(string dataGroup, string url, int testEnvironmentId, DateTime? startDate, DateTime? endDate, int? numTests, int? numThreads);

		/// <summary>
		/// Gets a load test run detail for a given datagroup, url and testEnvironmentId
		/// </summary>
		/// <param name="dataGroup">The data group</param>
		/// <param name="url">The url</param>
		/// <param name="testEnvironmentId">The test environment id</param>
		/// <param name="startDate">The start date range</param>
		/// <param name="endDate">The end date range</param>
		/// <returns>A list of LoadTestRunData objects</returns>
		[Obsolete]
		[OperationContract]
		List<LoadTestRunData> GetLoadTestRun(string dataGroup, string url, int testEnvironmentId, DateTime? startDate, DateTime? endDate);

		/// <summary>
		/// Deletes a test run task
		/// </summary>
		/// <param name="testRunTaskId"></param>
		[OperationContract]
		void DeleteTestRunTask(long testRunTaskId);

		/// <summary>
		/// Finishes a test run
		/// </summary>
		/// <param name="testRunId"></param>
		/// <param name="runStatusId"></param>
		/// <param name="runFinishDate"></param>
		[OperationContract]
		void FinishTestRun(int testRunId, int runStatusId, DateTime runFinishDate);

		/// <summary>
		/// Finishes a test run task
		/// </summary>
		/// <param name="testRunTaskId"></param>
		/// <param name="taskStatusId"></param>
		/// <param name="taskFinishDate"></param>
		[OperationContract]
		void FinishTestRunTask(long testRunTaskId, int taskStatusId, DateTime taskFinishDate);

		/// <summary>
		/// Starts a test run
		/// </summary>
		/// <param name="testName"></param>
		/// <param name="environmentName"></param>
		/// <param name="libraryName"></param>
		/// <param name="runStatusId"></param>
		/// <param name="testClassName"></param>
		/// <param name="runStartDate"></param>
		/// <param name="testLibraryRunId"></param>
		/// <returns>TestRunId</returns>
		[OperationContract]
		int StartTestRun(string testName, string environmentName, string libraryName, int runStatusId, string testClassName, DateTime runStartDate, int? testLibraryRunId);

		/// <summary>
		/// Inserts a test run task log entry
		/// </summary>
		/// <param name="testRunTaskId"></param>
		/// <param name="entryStatusId"></param>
		/// <param name="url"></param>
		/// <param name="entry"></param>
		/// <param name="entryCreateDate"></param>
		/// <returns>testRunTaskLogEntryId</returns>
		[OperationContract]
		long InsertTestRunTaskLogEntry(long testRunTaskId, int entryStatusId, string url, string entry, DateTime entryCreateDate);

		/// <summary>
		/// Starts a test run task
		/// </summary>
		/// <param name="parentTestRunTaskId"></param>
		/// <param name="testRunId"></param>
		/// <param name="taskName"></param>
		/// <param name="taskStatusId"></param>
		/// <param name="taskStartDate"></param>
		/// <returns>testRunTaskId</returns>
		[OperationContract]
		long StartTestRunTask(long? parentTestRunTaskId, int testRunId, string taskName, int taskStatusId,
							 DateTime taskStartDate);

		/// <summary>
		/// Inserts a test run task attribute
		/// </summary>
		/// <param name="testRunTaskId"></param>
		/// <param name="attributeName"></param>
		/// <param name="attributeValue"></param>
		/// <returns>testRunTaskAttributeId</returns>
		[OperationContract]
		long InsertTestRunTaskAttribute(long testRunTaskId, string attributeName, string attributeValue);
	

		/// <summary>
		/// Inserts a test monitor row
		/// </summary>
		/// <param name="testMonitorTypeId"></param>
		/// <param name="taskStatusId"></param>
		/// <param name="createDate"></param>
		/// <param name="testRunId"></param>
		/// <param name="message"></param>
		[OperationContract]
		void InsertTestMonitor(int testMonitorTypeId, int taskStatusId, DateTime createDate, int testRunId, string message);

		/// <summary>
		/// Inserts a network traffic url
		/// </summary>
		/// <param name="testRunId"></param>
		/// <param name="browserUrl"></param>
		/// <param name="browserUrlCounter"></param>
		/// <param name="remoteControlUrl"></param>
		/// <param name="msUntilReady"></param>
		/// <param name="traffic"></param>
		/// <returns>TrafficUrlId</returns>
		[OperationContract]
		void InsertNetworkTrafficUrl(int testRunId, string browserUrl, int browserUrlCounter, string remoteControlUrl,
									int msUntilReady, List<NetworkTrafficData> traffic);

		/// <summary>
		/// Starts a test library run
		/// </summary>
		/// <param name="environmentName"></param>
		/// <param name="libraryName"></param>
		/// <param name="startDate"></param>
		/// <param name="host"></param>
		/// <returns>TestLibraryId</returns>
		[OperationContract]
		int? StartTestLibraryRun(
			string environmentName,
			string libraryName,
			DateTime startDate,
			string host);

		/// <summary>
		/// Returns the number of tests currently running for a given environment
		/// </summary>
		/// <param name="testEnvironmentId">The testEnvironmentId you'd like to check</param>
		/// <returns></returns>
		[OperationContract]
		int GetCurrentActiveTestCount(int testEnvironmentId);

		/// <summary>
		/// Returns the active tests currently running for a given environment
		/// </summary>
		/// <param name="testEnvironmentId">The testEnvironmentId you'd like to check</param>
		/// <returns></returns>
		[OperationContract]
		List<ViewTestRun> GetCurrentActiveTests(int testEnvironmentId);

		/// <summary>
		/// Adds a list of revisions to a test library run
		/// </summary>
		/// <param name="revisions"></param>
		[OperationContract]
		void AddTestLibraryRunRevisions(IEnumerable<TestLibraryRunTeamRevision> revisions);

		/// <summary>
		/// Inserts a new pre-created object
		/// </summary>
		/// <param name="testEnvironmentId">the test environment id</param>
		/// <param name="objectType">The type of object</param>
		/// <param name="objectKey">The key to the object</param>
		[OperationContract]
		void InsertPreCreatedObject(int testEnvironmentId, string objectType, string objectKey);

		/// <summary>
		/// Gets a pre-created object key
		/// </summary>
		/// <param name="testEnvironmentId">the test environment id</param>
		/// <param name="objectType">The type of the object</param>
		/// <returns>A key to the object</returns>
		[OperationContract]
		string GetPreCreatedObject(int testEnvironmentId, string objectType);

		/// <summary>
		/// Gets count of available pre-created object keys as this instant
		/// </summary>
		/// <param name="testEnvironmentId">the test environment id</param>
		/// <param name="objectType">The type of the object</param>
		/// <returns>A key to the object</returns>
		[OperationContract]
		int GetPreCreatedObjectCount(int testEnvironmentId, string objectType);

		/// <summary>
		/// Removes all pre-created objects by the type
		/// </summary>
		/// <param name="testEnvironmentId">the test environment id</param>
		/// <param name="objectType">The type of the object</param>
		[OperationContract]
		void ClearPreCreatedObjects(int testEnvironmentId, string objectType);

		[OperationContract]
		List<ViewFailedTestPercentagesOverallResult> GetFailedTestPercentagesOverall(DateTime? from, DateTime? to);

		[OperationContract]
		List<ViewFailedTestPercentage> GetFailedTestPercentages(string environment, string libraryname,
																string fulltestname, DateTime? from, DateTime? to);


		/// <summary>
		/// Get record(s) from AsyncTask table.
		/// </summary>
		/// <param name="testName">String representing AsyncTask record name.</param>
		/// <param name="statusId">Int representing AsyncTask record status.</param>
		[OperationContract]
		List<AsyncTask> GetAsyncTasksByName(string testName, int statusId);

		/// <summary>
		/// Get all records from the AsyncTask table with the given status id in the 
		/// test environment.
		/// </summary>
		/// <param name="statusId">Int representing AysncTask record status.</param>
		/// <param name="environmentId">The environment id to retrieve taks for.</param>
		/// <returns>A list of <see cref="AsyncTask"/> objects.</returns>
		[OperationContract]
		List<AsyncTask> GetAllAsyncTasks(int statusId, int environmentId);

			/// <summary>
		/// Get count of records from AsyncTask table.
		/// </summary>
		/// <param name="testName">String representing AsyncTask record name.</param>
		/// <param name="statusId">Int representing AsyncTask record status.</param>
		[OperationContract]
		int GetAsyncTasksByNameCount(string testName, int statusId);


		/// <summary>
		/// Insert record into AsyncTask table.
		/// </summary>
		/// <param name="asyncTask">Object representing AsyncTask record.</param>
		[OperationContract]
		int InsertAsyncTask(AsyncTask asyncTask);


		/// <summary>
		/// Update record in AsyncTask table.
		/// </summary>
		/// <param name="asyncTask">Object representing AsyncTask record. Must have AsyncTaskID.</param>
		[OperationContract]
		void UpdateAsyncTask(AsyncTask asyncTask);


		/// <summary>
		/// Update record in TestRun table. NOTE: This is not a generic update method as it currently only supports updating the status.
		///  TODO: Find out if this should support updating all columns, and how to best do this conditionally with LINQ.
		/// </summary>
		/// <param name="testRun">Object representing TestRun record. Must have TestRunId.</param>
		[OperationContract]
		void UpdateTestRun(TestRun testRun);


		/// <summary>
		/// Update record in TestRunTask table. NOTE: This is not a generic update method as it currently only supports updating the status.
		///  TODO: Find out if this should support updating all columns, and how to best do this conditionally with LINQ.
		/// </summary>
		/// <param name="testRunTask">Object representing TestRunTask record. Must have TestRunId and TaskName.</param>
		[OperationContract]
		void UpdateTestRunTask(TestRunTask testRunTask);
	}
}